// 引入其他类
import Food from './Food';
import ScorePanel from './ScorePanel';
import Snake from './Snake';

// 游戏控制器，控制其他的所有类
class GameControl {
	// 蛇
	private snake: Snake;
	// 食物
	private food: Food;
	// 记分牌
	private scorePanel: ScorePanel;
	// 创建一个属性来存储蛇的移动方向（也就是按键的方向）
	direction: String = '';
	// 创建一个属性用来记录游戏是否结束
	private isLive: Boolean = true;

	constructor(maxLevel: number = 10, upScore: number = 10) {
		this.snake = new Snake();
		this.food = new Food();
		this.scorePanel = new ScorePanel(maxLevel, upScore);
		// 创建GameControl实例时初始化游戏
		this.init();
	}

	// 游戏的初始化方法，调用后游戏即开始
	init() {
		// 绑定键盘按键按下的事件
		document.addEventListener('keydown', this.keydownHandle);
		// 调用run方法，使蛇移动
		this.run();
	}

	/*
      Chrome     
      ArrowUp    
      ArrowDown  
      ArrowLeft  
      ArrowRight 
  */
	// 创建一个键盘按下的响应函数
	keydownHandle = (event: KeyboardEvent) => {
		// 修改direction属性
		this.direction = event.key;
	};

	// 创建一个控制蛇移动的方法
	run() {
		/*
		 *   根据方向（this.direction）来使蛇的位置改变
		 *       向上 top  减少
		 *       向下 top  增加
		 *       向左 left 减少
		 *       向右 left 增加
		 */
		// 获取蛇现在坐标
		let x = this.snake.X;
		let y = this.snake.Y;

		// 根据按键方向来计算X值和Y值（未更新）
		switch (this.direction) {
			case 'ArrowUp':
				y -= 10;
				break;
			case 'ArrowDown':
				y += 10;
				break;
			case 'ArrowLeft':
				x -= 10;
				break;
			case 'ArrowRight':
				x += 10;
				break;
		}

    // 检查蛇是否吃到食物
    this.checkEat(x, y);

		// 更新蛇的坐标
		try {
			this.snake.X = x;
			this.snake.Y = y;
		} catch (error: any) {
			// 进入到catch，说明出现了异常(撞墙或者撞到自己)，游戏结束，弹出一个提示信息
			alert(error.message);
			// 将isLive设置为false
			this.isLive = false;
		}

		// 开启一个定时调用（定时器调用自身）
		// 会再次创建一个定时器(递归)
		// 这里bind(this)保证方法里面的this永远GameControl的实例，也可以将run方法写成箭头函数
		this.isLive &&
			setTimeout(this.run.bind(this), 300 - (this.scorePanel.level - 1) * 30);
	}

	// 定义一个方法，用来检查蛇是否吃到食物
  checkEat (x: number, y: number) {
    if (x === this.food.X && y=== this.food.Y) {
			console.log('蛇吃到食物了');
			// 食物的位置要进行重置
			this.food.change();
			// 分数增加
      this.scorePanel.addScore();
			// 蛇要增加一节
      this.snake.addBody();
		}
  }
}

export default GameControl;
